﻿/*
 
    This file is part of AnkhBG.

    AnkhBG is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    AnkhBG is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with AnkhBG.  If not, see <http://www.gnu.org/licenses/>.
 
 */


using Glider.Common.Objects;

namespace AnkhBG
{
    public class QueueManager
    {
        #region Public Fields
        public Settings settings = Settings.Instance;

        // Check if we are queued by looking for the MiniMap-Icon
        public static bool IsQueued
        {
            get
            {
                GInterfaceObject frame = GContext.Main.Interface.GetByName("MiniMapBattlefieldFrame");
                return (frame != null && frame.IsVisible);
            }
        }

        // Check if we can enter a battleground by looking for the StaticPopup-frames
        public static bool CanEnter
        {
            get
            {
                for (int i = 1; i <= 4; ++i)
                {
                    GInterfaceObject obj = GContext.Main.Interface.GetByName("StaticPopup" + i.ToString());
                    if (obj == null || !obj.IsVisible)
                        continue;

                    GInterfaceObject text = obj.GetChildObject("StaticPopup" + i.ToString() + "Text");
                    if (text == null || !text.LabelText.StartsWith("You are now eligible to enter"))
                        continue;

                    return true;
                }

                return false;
            }
        }

        // Check if the battleground is over by looking for the Leave-Button
        public static bool CanLeave
        {
            get
            {
                GInterfaceObject obj = GContext.Main.Interface.GetByName("WorldStateScoreFrameLeaveButton");
                if (obj != null && obj.IsVisible)
                    return true;
                else
                    return false;
            }
        }
        #endregion


        #region Contructors

        public QueueManager()
        {
        }

        ~QueueManager()
        {
        }

        #endregion


        #region Public Methods
        // Accept the Queue-Dialog / Enter the battleground
        // returns an error-code (anything > 0 means an error occured)
        public int Enter()
        {
            if (CanEnter)
            {
                int popup = 0;
                for (int i = 1; i <= 4; ++i)
                {
                    GInterfaceObject obj = GContext.Main.Interface.GetByName("StaticPopup" + i.ToString());
                    if (obj == null || !obj.IsVisible)
                        continue;
                    GInterfaceObject text = obj.GetChildObject("StaticPopup" + i.ToString() + "Text");
                    if (text == null || !text.LabelText.StartsWith("You are now eligible to enter"))
                        continue;
                    popup = i;
                    break;
                }
                if (popup > 0)
                {
                    GInterfaceObject obj = GContext.Main.Interface.GetByName("StaticPopup" + popup.ToString() + "Button1");
                    if (obj != null && obj.IsVisible)
                    {
                        GContext.Main.EnableCursorHook();
                        obj.Hover();
                        obj.ClickMouse(false);
                        GContext.Main.DisableCursorHook();

                        return 0;
                    }
                    else
                        return 3;
                }
                else
                    return 2;
            }
            else
                return 1; // can't enter yet
        }

        // Leave the Queue
        // returns an error-code (anything > 0 means an error occured)
        public int Leave()
        {
            if (CanLeave)
            {
                GInterfaceObject obj = GContext.Main.Interface.GetByName("WorldStateScoreFrameLeaveButton");
                GContext.Main.EnableCursorHook();
                obj.Hover();
                obj.ClickMouse(false);
                GContext.Main.DisableCursorHook();
                return 0;
            }
            else
                return 1;
        }

        // Queue up
        // returns an error-code (anything > 0 means an error occured)
        public int Queue()
        {
            if (IsQueued)
            {
                return 1; // is not queued
            }
            else
            {
                GUnit[] units = GObjectList.GetUnits();
                GUnit npc = null;
                foreach (GUnit unit in units)
                {
                    if (unit.IsMonster && !unit.IsDead) // yes NPCs are monsters... cruel truth
                    {
                        if (
                                ( // find closest NPC
                                    (settings.QueueType == "closest" || settings.QueueType == "") &&
                                    (
                                        unit.Title == "Alterac Valley Battlemaster" ||
                                        unit.Title == "Arathi Basin Battlemaster" ||
                                        unit.Title == "Warsong Gulch Battlemaster" ||
                                        unit.Title == "Eye of the Storm Battlemaster"
                                    )
                                ) ||
                                ( // find specific battlemaster
                                    settings.QueueType == "specific" &&
                                    unit.Title.ToLower() == (settings.QueueBG + " battlemaster").ToLower()
                                )
                            )
                        {
                            if (npc == null)
                                npc = unit;
                            if (unit.DistanceToSelf < npc.DistanceToSelf)
                                npc = unit;
                        }
                    }
                }

                if (npc == null)
                {
                    if (settings.QueueType == "specific")
                    {
                        if (settings.QueueBG == "")
                            Main.Instance.Window.LogError("Please select a Battleground before starting.");
                        else
                            Main.Instance.Window.LogError("The battlemaster was not found.");
                    }
                    else
                        Main.Instance.Window.LogError("There are no NPCs around you!");

                    return 2;
                }
                else
                {
                    double approach_distance = 2.0f;
                    if (npc.DistanceToSelf > approach_distance)
                    {
                        Main.Instance.Window.Log("Trying to approach " + npc.Name);
                        if (!GContext.Main.Movement.MoveToUnit(npc, approach_distance, false))
                        {
                            Main.Instance.Window.LogError("Couldn't approach " + npc.Name);
                            return 6;
                        }
                    }

                    Main.Instance.Window.Log("Trying to talk to " + npc.Name + ".");

                    for (int loops = 0; GContext.Main.Me.Target != null && loops <= 5; ++loops)
                    {
                        GContext.Main.Debug("AnkhBG: Target not clear, trying to clear with Common.Escape");
                        GContext.Main.SendKey("Common.Escape"); // clear target / close window
                    }

                    GContext.Main.EnableCursorHook();
                    npc.Hover();
                    bool interacted = false;
                    for (int loops = 0; !interacted && loops <= 7; ++loops)
                    {
                        interacted = npc.Interact();
                        if (interacted == false)
                        {
                            GContext.Main.Debug("AnkhBG: Interacting failed, trying again (" + loops + ").");
                            GContext.Main.Movement.MoveToUnit(npc, 0.8f, false);
                            npc.Face();
                            System.Threading.Thread.Sleep(500);
                        }
                    }
                    GContext.Main.DisableCursorHook();

                    // Try 4 times to find the Join-Button (because of lag etc.)
                    for (int tries = 7; tries >= 0; --tries)
                    {
                        System.Threading.Thread.Sleep(1500);

                        GInterfaceObject BattlefieldJoinFrame = GContext.Main.Interface.GetByName("BattlefieldFrameJoinButton");
                        if (BattlefieldJoinFrame != null && BattlefieldJoinFrame.IsVisible)
                        { // Join Battle
                            GContext.Main.EnableCursorHook();
                            BattlefieldJoinFrame.Hover();
                            BattlefieldJoinFrame.ClickMouse(false);
                            Main.Instance.Window.Log("We should be queued now.");
                            GContext.Main.DisableCursorHook();
                            break;
                        }
                        else
                        { // Join-Button was not found
                            if (BattlefieldJoinFrame == null)
                                GContext.Main.Debug("AnkhBG: BattlefieldJoinFrame == null (" + tries + ").");
                            else if (BattlefieldJoinFrame.IsVisible == false)
                                    GContext.Main.Debug("AnkhBG: BattlefieldJoinFrame.IsVisible == false (" + tries + ").");
                            if (tries == 0)
                            {
                                Main.Instance.Window.LogError("Couldn't find Join-Button.");
                                return 4; // Join-Button was not found
                            }
                            else
                            {
                                System.Threading.Thread.Sleep(2000);
                                continue; // we still have more tries
                            }
                        }
                    }
                    return 0; // no error
                }
            }
        }
        #endregion
    }
}